package com.example.geoaimavlink_android.activity.view.obstacle

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageFormat
import android.graphics.Matrix
import android.graphics.Rect
import android.graphics.YuvImage
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.geoaimavlink_android.R
import com.example.geoaimavlink_android.activity.utils.YUVUtil
import com.geoai.mavlink.geoainet.base.mavlinkcore.controller.StarLinkClientManager
import com.geoai.module.common.DateHelperUtils
import com.geoai.module.common.thread.ExecutorsManager
import com.geoai.module.common.thread.TaskType
import com.geoai.widget.constant.CodecMode
import com.geoai.widget.constant.PlayNode
import com.geoai.widget.constant.RenderMode
import com.geoai.widget.setting.YFVParams
import com.libyuv.util.YuvUtil
import kotlinx.android.synthetic.main.activity_calibration.btn_start_record
import kotlinx.android.synthetic.main.activity_calibration.btn_stop_record
import kotlinx.android.synthetic.main.activity_calibration.edt_record_file_path
import kotlinx.android.synthetic.main.activity_calibration.image_result
import kotlinx.android.synthetic.main.activity_calibration.video
import kotlinx.android.synthetic.main.frag_vision_calibration.img_result
import java.io.ByteArrayOutputStream
import java.io.File
import java.util.concurrent.Future

/**
 * @Author      : Ronny
 * @Email       : Ronny_xie@hotmail.com
 * @Date        : on 2024-05-31 16:34.
 * @Description :
 */
class CalibrationActivity: AppCompatActivity() {

    private val retData by lazy { ByteArray(6000000) }//随便申请的空间

    private lateinit var OBSTACLE_FILE_PATH: String

    private lateinit var mFcSn: String

    private lateinit var mMode: String

    private lateinit var mID: String

    private var mThreadSubmit: Future<*>? = null

    private lateinit var mRecordFilePath: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_calibration)

        mRecordFilePath = getExternalFilesDir(null)!!.path + File.separator + "ObstacleCalibrationRecord" + File.separator

        OBSTACLE_FILE_PATH = getExternalFilesDir("")?.path!! + File.separator + "ObstacleCalibration"

        if (!File(OBSTACLE_FILE_PATH).exists()) {
            File(OBSTACLE_FILE_PATH).mkdirs()
        }

        if (!File(mRecordFilePath).exists()) {
            File(mRecordFilePath).mkdirs()
        }

        mMode = intent.getStringExtra("mode")!!

        mFcSn = intent.getStringExtra("sn")!!

        mID = intent.getStringExtra("id")!!

        initCalibrationThread()

        initVideo()

        initImageThread()

        //这里还需要一个线程，一直去扫目录，是否生成文件
    }

    private fun initImageThread() {
        mThreadSubmit = ExecutorsManager.get().submit("", TaskType.IO) {
            while (true) {
                val bitmap = video.getBitmap() ?: continue
                val newBitmap = getResizedBitmap(bitmap, 1024, 384)
                val width = newBitmap.width
                val height = newBitmap.height

                val nv21 = YUVUtil.fetchNV21(newBitmap)

                val i420 = ByteArray(width * height * 2)
                YuvUtil.yuvNV21ToI420(nv21, width, height, i420)

                val yv12 = ByteArray(width * height * 2)
                YuvUtil.yuvI420ToYV12(i420, width, height, width, yv12)

                val ret = StarLinkClientManager.getInstance().getProduct(mID.toInt())?.obstacleManager?.startObstacleCalibration(
                    yv12,
                    retData,
                    width,
                    height
                )

                val i420R = ByteArray(width * height * 2)
                YuvUtil.yuvYV12ToI420(retData, width, height, i420R)

                val nv21R = ByteArray(width * height * 2)
                YuvUtil.yuvI420ToNV21(i420R, width, height, nv21R)

                val yuvImage = YuvImage(nv21R, ImageFormat.NV21, width, height, null)
                val outputStream = ByteArrayOutputStream()
                yuvImage.compressToJpeg(Rect(0, 0, width, height), 100, outputStream)
                val array = outputStream.toByteArray()

                bitmap.recycle()
                newBitmap.recycle()

                runOnUiThread {
                    image_result?.setImageBitmap(
                        BitmapFactory.decodeByteArray(
                            array,
                            0,
                            array.size
                        )
                    )
                }
            }
        }
    }

    private fun initCalibrationThread() {
        val path = OBSTACLE_FILE_PATH + File.separator + mFcSn + File.separator + mMode + "_"+ System.currentTimeMillis() +"_未上传.vc"

        val product = StarLinkClientManager.getInstance().getProduct(mID.toInt())

        if (product != null && product.isConnected) {
            product.obstacleManager.initObstacleCalibrationLibrary(path, 20.0f, 2000)
            runOnUiThread { Toast.makeText(this@CalibrationActivity, "启动校准", Toast.LENGTH_LONG).show() }
        }
    }

    private fun initVideo() {
        val recordPath = mRecordFilePath + "record-" + DateHelperUtils.getDateSeries() + ".h265"

        edt_record_file_path?.setText(recordPath)

        video.initPlayer(YFVParams.Builder()
            .setPlayNode(PlayNode.VISION_CALIBRATION)
            .setSurfaceMode(RenderMode.RENDER_TEXTURE_VIEW)
            .setVideoCodecMode(CodecMode.HARDWARE)
            .setRecordOutputFile(recordPath)
            .build())
        video.startPlayer()

        btn_start_record.setOnClickListener {
            video.startRecord()
            Toast.makeText(this, "start record", Toast.LENGTH_SHORT).show()
        }
        btn_stop_record.setOnClickListener {
            video.stopRecord()
            Toast.makeText(this, "stop record", Toast.LENGTH_SHORT).show()
        }
    }

    private fun getResizedBitmap(bm: Bitmap, newWidth: Int, newHeight: Int): Bitmap {
        val width = bm.width
        val height = bm.height
        val scaleWidth = newWidth.toFloat() / width
        val scaleHeight = newHeight.toFloat() / height
        // CREATE A MATRIX FOR THE MANIPULATION
        val matrix = Matrix()
        // RESIZE THE BIT MAP
        matrix.postScale(scaleWidth, scaleHeight)

        // "RECREATE" THE NEW BITMAP
        val resizedBitmap = Bitmap.createBitmap(
            bm, 0, 0, width, height, matrix, false
        )
        bm.recycle()
        return resizedBitmap
    }
}